package parsetree;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Position;


public abstract class AbstractLeafElement extends AbstractElement {
    
    private transient Position startPosition;
    
    public AbstractLeafElement(BranchElement parent, int startOffset) throws BadLocationException
    {
        super(parent.getParseTree(), parent);
        startPosition = getDocument().createPosition(startOffset);
    }
    
    public AbstractLeafElement(BranchElement parent, Position startPosition)
    {
        super(parent.getParseTree(), parent);
        this.startPosition = startPosition;
    }
    
    @Override
    public boolean isLeaf()
    {
        return true;
    }
    
    @Override
    public int getStartOffset()
    {
        return getStartPosition().getOffset();
    }
    
    @Override
    public int getChildCount()
    {
        return 0;
    }
    
    @Override
    public boolean hasChildren()
    {
        return false;
    }
    
    @Override
    public int getElementIndex(int offset)
    {
        return 0;
    }
    
    @Override
    public int getElementCount()
    {
        return 0;
    }
    
    @Override
    public Element getElement(int index)
    {
        return null;
    }
    
    @Override
    public Element[] split(int modelOffset) throws BadLocationException
    {
        if(modelOffset <= getStartOffset()) {
            throw new BadLocationException(String.format(
                    "Model offset %d at or before the start of the element in split.",
                    modelOffset), modelOffset);
        }
        if(modelOffset >= getEndOffset()) {
            throw new BadLocationException(
                    String.format(
                            "Model offset %d at or after the end of the element in split.",
                            modelOffset), modelOffset);
        }
        
        Element firstElement = getElementBefore(modelOffset);
        Element secondElement = getElementAfter(modelOffset);
        AttributeSet attributes = getAttributes();
        firstElement.setAttributes(attributes);
        secondElement.setAttributes(attributes);
        
        return new Element[] { firstElement, secondElement };
    }
    
    protected Element getElementBefore(int modelOffset) throws BadLocationException
    {
        return new ParsingElement(getParent(), getStartOffset(), modelOffset);
    }
    
    protected Element getElementAfter(int modelOffset) throws BadLocationException
    {
        return new ParsingElement(getParent(), modelOffset, getEndOffset());
    }
    
    /**
     * @return the startPosition
     */
    protected Position getStartPosition()
    {
        return startPosition;
    }
    
    private void writeObject(ObjectOutputStream out) throws IOException
    {
        out.writeInt(getStartOffset());
        out.writeInt(getEndOffset());
    }
    
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
    {
        //TODO
    }
    
    @Override
    public void writeExternal(ObjectOutput out) throws IOException
    {
        super.writeExternal(out);
        out.writeInt(getStartOffset());
        out.writeInt(getEndOffset());
    }
    
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
    {
        //TODO
    }
}